package cn.xiyun.xiyuncc.service.impl;

import cn.xiyun.xiyuncc.domain.CourseOrder;
import cn.xiyun.xiyuncc.domain.CourseOrderItem;
import cn.xiyun.xiyuncc.dto.KillOrderDto;
import cn.xiyun.xiyuncc.dto.Order2PayDto;
import cn.xiyun.xiyuncc.dto.PlaceOrderDto;
import cn.xiyun.xiyuncc.feignClient.CourseFeignClient;
import cn.xiyun.xiyuncc.mapper.CourseOrderMapper;
import cn.xiyun.xiyuncc.result.JSONResult;
import cn.xiyun.xiyuncc.service.ICourseOrderItemService;
import cn.xiyun.xiyuncc.service.ICourseOrderService;
import cn.xiyun.xiyuncc.util.AssertUtil;
import cn.xiyun.xiyuncc.util.CodeGenerateUtils;
import cn.xiyun.xiyuncc.vo.CourseInfoVO;
import cn.xiyun.xiyuncc.vo.OrderDataVO;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author xiyun.maple
 * @since 2023-03-20
 */
@Service
public class CourseOrderServiceImpl extends ServiceImpl<CourseOrderMapper, CourseOrder> implements ICourseOrderService {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
    @Autowired
    private CourseFeignClient courseFeignClient;
    @Autowired
    private ICourseOrderItemService courseOrderItemService;
    @Autowired
    private CourseOrderMapper courseOrderMapper;


    @Value("${rocketmq.producer.send-message-timeout}")  //读取配置文件 group
    private Integer messageTimeOut;

    /**
     * 创建订单与发送事务消息创建支付单
     *
     * @param placeOrderDto
     * @return
     */
    @Override
    public String placeOrder(PlaceOrderDto placeOrderDto) {
        // 获取课程id
        List<Long> courseIds = placeOrderDto.getCourseIds();
        String ids = courseIds.stream().map(Object::toString).collect(Collectors.joining(","));
        String token = placeOrderDto.getToken();
        // TODO 当前登录人id
        Long loginId = 3L;
        String redisKey = loginId + ":" + ids;
        String redisToken = redisTemplate.opsForValue().get(redisKey).toString();
        AssertUtil.isNotNull(redisToken, "信息有误请稍后重试");
        AssertUtil.isEquals(token, redisToken, "信息有误请稍后重试");
        // 查询订单课程信息
        JSONResult jsonResult = courseFeignClient.orderData(ids);
        AssertUtil.isTrue(jsonResult.isSuccess(), "课程服务繁忙请稍后重试");
        OrderDataVO orderDataVO = JSON.parseObject(JSON.toJSONString(jsonResult.getData()), OrderDataVO.class);

/*        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dateNowStr = sdf.format(date);*/
        // 生成订单号
        String orderCode = CodeGenerateUtils.generateOrderSn(loginId);
        // 创建主订单
        CourseOrder courseOrder = new CourseOrder();
        courseOrder.setCreateTime(new Date());
        courseOrder.setOrderNo(orderCode);
        courseOrder.setTotalAmount(orderDataVO.getTotalAmount());
        courseOrder.setTotalCount(1);
        courseOrder.setStatusOrder(CourseOrder.ORDER_UNPAID);
        courseOrder.setUserId(loginId);
        courseOrder.setTitle("购买课程");
        courseOrder.setPayType(placeOrderDto.getPayType());
        // 获取课程详细信息
        List<CourseInfoVO> courseInfos = orderDataVO.getCourseInfos();
        courseInfos.forEach(courseInfoVO -> {
            // 创建子订单
            CourseOrderItem courseOrderItem = new CourseOrderItem();
            courseOrderItem.setCourseId(courseInfoVO.getCourse().getId());
            courseOrderItem.setCount(1);
            courseOrderItem.setAmount(courseInfoVO.getCourseMarket().getPrice());
            courseOrderItem.setCreateTime(new Date());
            courseOrderItem.setCourseName(courseInfoVO.getCourse().getName());
            courseOrderItem.setCoursePic(courseInfoVO.getCourse().getPic());
            courseOrderItem.setOrderNo(orderCode);
            // 将 子订单 放入主订单 的List集合中
            courseOrder.getList().add(courseOrderItem);
        });
        // 发送事务消息 创建支付单.
        // 创建支付单对象
        Order2PayDto order2PayDto = new Order2PayDto();
        order2PayDto.setOrderNo(orderCode);
        order2PayDto.setAmount(orderDataVO.getTotalAmount());
        order2PayDto.setPayType(placeOrderDto.getPayType());
        order2PayDto.setLoginId(loginId);
        order2PayDto.setSubject("购买课程");
        //封装消息
        Message<String> message = MessageBuilder.withPayload(JSON.toJSONString(order2PayDto)).build();
        //发送事务消息
        rocketMQTemplate.sendMessageInTransaction(
                //这里和事务监听器里面的事务组保持一致
                "createOrder-message-group",
                //topic:tag
                "createOrder_topic:createOrder_tags", message, courseOrder);

        // 发送延时消息, 传递订单号 ,判断订单与支付单状态,未支付则修改订单与支付单状态为超时
        rocketMQTemplate.syncSend(
                "OrderTimeOut_topic:OrderTimeOut_tags",
                MessageBuilder.withPayload(orderCode).build(),
                // TODO 定时等级15 = 20分钟
                messageTimeOut, 15);
        // 给前端返回订单号,根据订单号查询支付单
        return orderCode;
    }


    /**
     *  秒杀订单生成
     * @param placeOrderDto
     * @return
     */
    @Override
    public String killPlaceOrder(PlaceOrderDto placeOrderDto) {
        // 获取课程id
        String orderNo = placeOrderDto.getOrderNo();
        Object o = redisTemplate.opsForValue().get(orderNo);
        KillOrderDto killOrderDto = (KillOrderDto) o;
        String token = placeOrderDto.getToken();
        // TODO 当前登录人id
        Long loginId = killOrderDto.getLogId();
        String redisKey = loginId + ":" + killOrderDto.getCourseId();
        String redisToken = redisTemplate.opsForValue().get(redisKey).toString();
        AssertUtil.isNotNull(redisToken, "信息有误请稍后重试");
        AssertUtil.isEquals(token, redisToken, "信息有误请稍后重试");
        // 查询订单课程信息
        JSONResult jsonResult = courseFeignClient.orderData(killOrderDto.getCourseId().toString());
        AssertUtil.isTrue(jsonResult.isSuccess(), "课程服务繁忙请稍后重试");
        OrderDataVO orderDataVO = JSON.parseObject(JSON.toJSONString(jsonResult.getData()), OrderDataVO.class);

        // 生成订单号
        String orderCode =killOrderDto.getOrderNo();
        // 创建主订单
        CourseOrder courseOrder = new CourseOrder();
        courseOrder.setCreateTime(new Date());
        courseOrder.setOrderNo(orderCode);
        courseOrder.setTotalAmount(killOrderDto.getKillPrice());
        courseOrder.setTotalCount(1);
        courseOrder.setStatusOrder(CourseOrder.ORDER_UNPAID);
        courseOrder.setUserId(loginId);
        courseOrder.setTitle("购买秒杀课程");
        courseOrder.setPayType(placeOrderDto.getPayType());
        // 获取课程详细信息
        List<CourseInfoVO> courseInfos = orderDataVO.getCourseInfos();
        courseInfos.forEach(courseInfoVO -> {
            // 创建子订单
            CourseOrderItem courseOrderItem = new CourseOrderItem();
            courseOrderItem.setCourseId(courseInfoVO.getCourse().getId());
            courseOrderItem.setCount(1);
            courseOrderItem.setAmount(killOrderDto.getKillPrice());
            courseOrderItem.setCreateTime(new Date());
            courseOrderItem.setCourseName(courseInfoVO.getCourse().getName());
            courseOrderItem.setCoursePic(courseInfoVO.getCourse().getPic());
            courseOrderItem.setOrderNo(orderCode);
            // 将 子订单 放入主订单 的List集合中
            courseOrder.getList().add(courseOrderItem);
        });
        // 发送事务消息 创建支付单.
        // 创建支付单对象
        Order2PayDto order2PayDto = new Order2PayDto();
        order2PayDto.setOrderNo(orderCode);
        order2PayDto.setAmount(killOrderDto.getKillPrice());
        order2PayDto.setPayType(placeOrderDto.getPayType());
        order2PayDto.setLoginId(loginId);
        order2PayDto.setSubject("购买秒杀课程");
        //封装消息
        Message<String> message = MessageBuilder.withPayload(JSON.toJSONString(order2PayDto)).build();
        //发送事务消息
        rocketMQTemplate.sendMessageInTransaction(
                //这里和事务监听器里面的事务组保持一致
                "createOrder-message-group",
                //topic:tag
                "createOrder_topic:createOrder_tags", message, courseOrder);

        // 发送延时消息, 传递订单号 ,判断订单与支付单状态,未支付则修改订单与支付单状态为超时
        rocketMQTemplate.syncSend(
                "KIllOrderTimeOut_topic:KIllOrderTimeOut_tags",
                MessageBuilder.withPayload(JSON.toJSONString(killOrderDto)).build(),
                // TODO 定时等级15 = 20分钟
                messageTimeOut, 15);
        // 给前端返回订单号,根据订单号查询支付单
        // 删除redis中的预订单
        redisTemplate.delete(orderCode);
        return orderCode;
    }
    /**
     * 添加主订单与子订单
     */
    @Override
    public void insertOrder(CourseOrder courseOrder) {
        super.insert(courseOrder);
        courseOrder.getList().forEach(courseOrderItem -> {
            courseOrderItem.setOrderId(courseOrder.getId());
            courseOrderItemService.insert(courseOrderItem);
        });
    }

    /**
     * 用户查询订单数据
     * @return
     */
    @Override
    public List<CourseOrder> forUser() {
        List<CourseOrder> courseOrders = courseOrderMapper.forUser(3L);
        System.out.println(courseOrders);
        return courseOrders;
    }



}
